ε Optimización en ensamblador ε --------------------------- Continuamos con este cursillo de optimización. El número pasado vimos un poco de optimización en comparaciones, y hoy vamos a empezar con optimiza- ción de código. Para empezar, podemos ver el siguiente ejemplo: una rutina completamen- te sin optimizar que de ser así sería bastante más lenta de lo que podría ser optimizada. Vamos a verla: Γ MOV CX, 0100h Γ PUSH CS Γ POP DS Γ PUSH CS Γ POP ES Γ MOV DI, Offset Origen Γ MOV BX, Offset Destino Γ @@Loop: MOV DL, [DI] Γ CMP DL, 20h Γ JZ @@FinLoop Γ MOV [BX], DL Γ INC DI Γ INC BX Γ LOOP @@Loop Γ @@FinLoop: CMP CX, 0000 Γ JZ @@NoSeHaEncontradoUnEspacio Γ ... Esta porción de código, desde el punto de vista de optimización, es horrible. Esto haría que copiemos una cadena en la dirección [Origen] a una dirección de memoria [Destino] hasta que encontremos un espacio. Optimicemos paso a paso: Existen las instrucciones δLODSBπ y δSTOSBπ. δLODSBπ coge el byte que apun- ta ΩDS:SIπ y lo carga en ΩALπ, y ΩSTOSBπ almacena el byte ΩALπ en la zona en memoria apuntada por δES:DIπ. Además, el puntero en DS:SI y ES:DI se incrementa o decre- menta según la bandera δDπ (Direction Flag) esté a 1 o a 0 (si está a 0 se incre- menta, y a 1 se decrementa). Por tanto, usemos esto en el código. En vez de usar DL como variable para almacenar lo que cogemos de [Origen], usemos AL, y en vez de usar DI para el origen y BX para el destino, usemos SI para el origen y DI para el destino: Γ MOV CX, 0100h Γ PUSH CS Γ POP DS Γ PUSH CS Γ POP ES Γ MOV SI, Offset Origen Γ MOV DI, Offset Destino Γ CLD ; Pone la Direction Flag a 0 Γ @@Loop: LODSB Γ CMP AL, 20h Γ JZ @@FinLoop Γ STOSB Γ LOOP @@Loop Γ @@FinLoop: CMP CX, 0000 Γ JZ @@NoSeHaEncontradoUnEspacio Γ ... Bien, no sólo hemos aumentado la velocidad de este algoritmo, si no que además hemos reducido su tamaño. Pero vemos más animaladas, entre ellas la com- probación δCMP CX,0000π. Podríamos reducirlo a δOR CX,CX/JNZ ...π , pero aún así no está completamente optimizado. Usamos, entonces, la instrucción δJCXZπ. Esta instrucción es una instrucción de salto que se efectuará si CX es igual a 0. Lo malo de ésta es que no permite saltos de más de 128 bytes de longitud, pero si sabemos que éste no va a ser nuestro caso, la usamos: Γ ... Γ STOSB Γ LOOP @@Loop Γ @@FinLoop: JCXZ @@NoSeHaEncontradoUnEspacio Γ ... Y encima de más velocidad conseguimos reducción de código. Si seguimos repasando el código, nos encontramos con la última falta: LOOP. No es que LOOP sea una instrucción de poca optimización, pero resulta que el par δDEC CX/JNZ... es más rápido, al menos hasta el Pentium. Pero como no programamos para Pentium (de momento), habrá que desistir de usar LOOP. Así que, tocando esto último, miramos cómo nos ha quedado el código resultante: Γ MOV CX, 0100h Γ PUSH CS Γ POP DS Γ PUSH CS Γ POP ES Γ MOV SI, Offset Origen Γ MOV DI, Offset Destino Γ @@Loop: LODSB Γ CMP AL, 20h Γ JZ @@FinLoop Γ STOSB Γ DEC CX Γ JNZ @@Loop Γ @@FinLoop: JCXZ @@NoSeHaEncontradoUnEspacio Γ ... No sólo es más corto, sino más rápido (de buen trozo). Y, mirando mi- rando, nos damos cuenta de que aún podemos optimizarlo más aún. Si lo miramos bien, podemos ver que no hay ninguna necesidad de saltar a @@FinLoop después de comprobar que AL es 20h, sino que podemos saltar directamente al sitio que toca, y no utilizar @@FinLoop como lugar de paso tanto si se ha encontrado un espacio como si no, y tener que utilizar JCXZ para determinar si se encontró un espacio o no. Vamos a implementarlo: Γ MOV CX, 0100h Γ PUSH CS Γ POP DS Γ PUSH CS Γ POP ES Γ MOV SI, Offset Origen Γ MOV DI, Offset Destino Γ @@Loop: LODSB Γ CMP AL, 20h Γ JZ @@SeEncontróUnEspacio Γ STOSB Γ DEC CX Γ JNZ @@Loop Γ JMP @@NoSeHaEncontradoUnEspacio Γ@@SeEncontroUnEspacio: ... Ante todos estos cambios, pensamos: pero, ¿de verdad hace falta redu- cir tanto un código si hace lo mismo? Tenemos que tener en cuenta que es mejor cuanto más veloz. Imaginaos que tenéis que hacer el algoritmo 20000 veces. Con el primer ejemplo, seguro que tardaba el doble que el primero en hacerse, y así se notaría bastante la velocidad. Bueno, ya está bien por ahora. En el próximo número veremos instruccio- nes que pueden ser sustituidas por grupos de instrucciones que en conjunto se- rán más rápidas que la original. Hasta la próxima! ∞ Líyak el Oscuro